package cate.game.util.api;

import cate.common.util.GameResult;
import cp.solution.business.sys.app.GameAppEntity;
import cate.game.role.Role;
import cp.solution.define.ClientType;
import easy.java.codec.JsonCodec;
import easy.java.io.http.HttpClientHelper;
import easy.java.io.http.HttpRequestHelper;
import easy.java.practice.errorcode.EcResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.util.EntityUtils;

import java.util.HashMap;
import java.util.Map;

@Slf4j
public class ChatApi {

    public static final boolean CLIENT_DRIVE_MODE = true;

    private static final String CHAT_RULE_URL_V2 = "https://speech.233joy.com/v1/speech/";

    // 0-其他,1.玩家发言 2.角色名 3.公会名 4.公会公告
    public static final int TYPE_OTHER = 0;
    public static final int TYPE_CHAT = 1;
    public static final int TYPE_ROLE_NAME = 2;
    public static final int TYPE_GUILD_NAME = 3;
    public static final int TYPE_GUILD_ANNOUNCE = 4;

    //1 私聊，2 喇叭，3 邮件，4 世界，5 国家，6 工会/帮会，7 队伍，8 附近，9 其他
    public static final int MSG_TYPE_1 = 1;
    public static final int MSG_TYPE_2 = 2;
    public static final int MSG_TYPE_3 = 3;
    public static final int MSG_TYPE_4 = 4;
    public static final int MSG_TYPE_5 = 5;
    public static final int MSG_TYPE_6 = 6;
    public static final int MSG_TYPE_7 = 7;
    public static final int MSG_TYPE_8 = 8;
    public static final int MSG_TYPE_9 = 9;

    public static GameResult<String> checkPublic(Role role, String content, byte channel) {
        GameResult<String> r = new GameResult<>();
        if(CLIENT_DRIVE_MODE) {
            return r;
        }
        Values values = new Values();
        values.read(role);
        GameAppEntity app = role.getGame().apisLoader().console.gameApp.getByCode(values.gameId);
        if(app == null) {
            return r.fail("gameId="+values.gameId+" is null");
        }
        values.content = content;
        values.type = TYPE_CHAT;
        values.channel = channel;
        values.msgType = MSG_TYPE_4;
        values.gameKey = app.gameKey;
        return speechWrap(values);
    }

    public static EcResult checkRoleName(Role role, String name) {
        EcResult r = new EcResult().success();
        if(CLIENT_DRIVE_MODE) {
            return r;
        }
        Values values = new Values();
        values.read(role);
        GameAppEntity app = role.getGame().apisLoader().console.gameApp.getByCode(values.gameId);
        if(app == null) {
            return r.fail("gameId="+values.gameId+" is null");
        }
        values.content = name;
        values.type = TYPE_ROLE_NAME;
        values.channel = 0;
        values.msgType = MSG_TYPE_9;
        values.gameKey = app.gameKey;
        return speechWrap(values);
    }

    public static GameResult<String> checkGuildName(Role role, String guildName) {
        GameResult<String> r = new GameResult<>();
        if(CLIENT_DRIVE_MODE) {
            return r;
        }
        Values values = new Values();
        values.read(role);
        GameAppEntity app = role.getGame().apisLoader().console.gameApp.getByCode(values.gameId);
        if(app == null) {
            return r.fail("gameId="+values.gameId+" is null");
        }
        values.content = guildName;
        values.type = TYPE_GUILD_NAME;
        values.channel = 0;
        values.msgType = MSG_TYPE_6;
        values.gameKey = app.gameKey;
        return speechWrap(values);
    }

    public static EcResult checkGuildDeclaration(Role role, String content) {
        EcResult r = new EcResult().success();
        if(CLIENT_DRIVE_MODE) {
            return r;
        }
        Values values = new Values();
        values.read(role);
        GameAppEntity app = role.getGame().apisLoader().console.gameApp.getByCode(values.gameId);
        if(app == null) {
            return r.fail("gameId="+values.gameId+" is null");
        }
        values.content = content;
        values.type = TYPE_GUILD_ANNOUNCE;
        values.channel = 0;
        values.msgType = MSG_TYPE_6;
        values.gameKey = app.gameKey;
        return speechWrap(values);
    }

    public static class Values {
        public String content;
        public String gameId;
        public String channelCode;
        public int type;
        public String openId;
        public String ip;
        public String roleId;
        public String roleName;
        public int srvId;
        public String srvName;
        public int roleLevel;
        public int roleVip;
        public byte channel;
        public long power;
        public int msgType;
        public String targetOpenId;
        public String targetRoleName;
        public Integer guildId;
        public String guildName;
        public String clientType;
        public long paySum;
        public String gameKey;

        public void read(Role role) {
            this.gameId = role.getBase().gameId;
            this.channelCode = role.getBase().channelCode;
            this.openId = role.getBase().openId;
            this.ip = role.getBase().login.ip;
            this.roleId = role.getUid();
            this.roleName = role.getBase().name;
            this.srvId = role.getBase().srvId;
            this.srvName = role.getGame().config.gs.getName();
            this.roleLevel = role.getBase().level;
            this.roleVip = role.getBase().vip;
            this.power = role.getBase().power;
            this.clientType = role.getBase().login.clientType;
            this.paySum = role.getPay().paySum;
        }
    }

    public static GameResult<String> speechWrap(Values values) {
        Result r = speech(values);
        GameResult<String> er = new GameResult<>();
        er.code = r.ok ? EcResult.SUCCESS : EcResult.FAIL;
        er.data = r.content;
        er.message = r.message;
        return er;
    }

    // 叶子戏言论监控文档
    // http://docs.yezixigame.com/pages/sdk/other.html#_2%E3%80%81%E8%A8%80%E8%AE%BA%E6%8E%A5%E5%8F%A3
    public static Result speech(Values values) {
        Result r = new Result();
        if (values.content == null) {
            values.content = "";
        }
        int theGameId;
        try {
            theGameId = Integer.parseInt(values.gameId);
        } catch (Exception e) {
            r.ok = false;
            r.message = "chatApi only accept num gameId";
            return r;
        }
        int theChannelId;
        try {
            theChannelId = Integer.parseInt(values.channelCode);
        } catch (Exception e) {
            theChannelId = 0;
        }
        Map<String, Object> params = new HashMap<>();
        // gameID	int	是	游戏 ID，接入提供的游戏 ID
        params.put("gameid", theGameId);
        // channelid int 是 渠道标记，用户登录后下发的 channelid
        params.put("channelid", theChannelId);
        // content	string	是	用户提交的内容
        params.put("content", values.content);
        // type	int	是	内容类型  0-其他,1.玩家发言 2.角色名 3.公会名 4.公会公告
        params.put("type", values.type);
        // openid	string	是	用户标示，用户登录后下发的 openid
        params.put("openid", values.openId);
        // userip	string	是	用户 IP，用户客服端 IP，真实 IP
        params.put("userip", values.ip);
        // ports	int	是	用户端口，用户客服端端口，真实端口
        params.put("ports", "0");
        // roleid	string	是	角色 ID，游戏角色
        params.put("roleid", values.roleId);
        // rolename	string	是	角色名称，游戏角色
        params.put("rolename", values.roleName);
        // serverid	string	是	区服 ID，游戏区服
        params.put("serverid", values.srvId);
        // servername	string	是	区服名称，游戏区服
        params.put("servername", values.srvName);
        // rolelevel	int	是	角色等级，默认值 0
        params.put("rolelevel", values.roleLevel);
        // roleviplevel	int	否	角色 VIP 等级，默认值 0
        params.put("roleviplevel", values.roleVip);
        // ts	long	是	时间戳，毫秒
        params.put("ts", System.currentTimeMillis());
        // 发言频道，默认值 0
        params.put("channel", values.channel);
        // 战力值，默认值 0
        params.put("fightvalue", values.power);
        // 发言必传，1 私聊，2 喇叭，3 邮件，4 世界，5 国家，6 工会/帮会，7 队伍，8 附近，9 其他
        params.put("msgtype", values.msgType);
        // 私聊对象的用户标示，私聊必传
        if(StringUtils.isNotBlank(values.targetOpenId)) {
            params.put("popenid", values.targetOpenId);
        }
        // 私聊对象的角色名称，私聊必传
        if(StringUtils.isNotBlank(values.targetRoleName)) {
            params.put("prolename", values.targetRoleName);
        }
        // 公会 ID，公会公告必传
        if(values.guildId != null) {
            params.put("guildid", values.guildId);
        }
        //  	公会名称，公会公告必传
        if(StringUtils.isNotBlank(values.guildName)) {
            params.put("guildname", values.guildName);
        }
        // ostype 	string 	是 	系统类型: ANDROID/IOS
        if(StringUtils.equals(ClientType.IOS.value, values.clientType)) {
            params.put("ostype", "IOS");
        } else if(StringUtils.equals(ClientType.ANDROID.value, values.clientType)){
            params.put("ostype", "ANDROID");
        }
        // rechargeamount 	int 	是 	系统类型: 总充值额
        params.put("rechargeamount", values.paySum);
        // sign	string	是	签名，key
        // 为分配的参数{GameKey},md5("openid=%s&gameid=%d&roleid=%s&ts=%d&serverid=%s&key=%s")
        String signSrc = "openid=%s&gameid=%d&roleid=%s&ts=%d&serverid=%s&key=%s";
        String sign =
                DigestUtils.md5Hex(
                        String.format(
                                signSrc,
                                params.get("openid"),
                                params.get("gameid"),
                                params.get("roleid"),
                                params.get("ts"),
                                params.get("serverid"),
                                values.gameKey));
        params.put("sign", sign);
        //log.info("打印言论接口请求参数：{}", params);
        HttpPost pr = HttpRequestHelper.POST_P(CHAT_RULE_URL_V2, params);
        pr.setConfig(
                RequestConfig.custom()
                        .setConnectTimeout(3000)
                        .setConnectionRequestTimeout(3000)
                        .setSocketTimeout(3000)
                        .build());
        try {
            HttpResponse response = HttpClientHelper.getClient().execute(pr);
            String json = EntityUtils.toString(response.getEntity());
            Resp resp = JsonCodec.instance().decode(json, Resp.class);
            if (StringUtils.equals("200", resp.code)) {
                r.status = resp.data.status;
                if (resp.data.status == 1) {
                    r.ok = true;
                    r.content = resp.data.content;
                } else {
                    r.ok = false;
                    r.content = resp.data.content;
                    r.message = "包含敏感词";
                    r.forbidAdd = 6000;
                }
            } else if(StringUtils.equals("500", resp.code)) {
                log.error("言论监控SDK调用出错(500,叶子戏服务器异常,非我方bug)：{}", resp.msg);
                r.ok = false;
                r.content = values.content;
                r.message = ""+resp.msg+"@yzx";
            } else {
                log.error("言论监控SDK调用出错：{}", resp.msg);
                r.ok = false;
                r.message = resp.msg;
            }
        } catch (Exception e) {
            log.error("言论监控接口调用失败", e);
            r.ok = false;
            r.message = "web-err";
        }
        return r;
    }

    public static class Result {
        public boolean ok;
        public int status;
        public String message;
        public String content;
        public long forbidAdd;
    }

    public static class Resp {
        // "code": 200
        public String code;
        // "msg": "操作成功"
        public String msg;

        public RespData data = new RespData();
    }

    public static class RespData {
        // "status": 0,//status为0,言论不通过
        public int status;
        // "matchNum": "42",//status为0,matchNum返回匹配上的言论序号
        public String matchNum;
        // "content": ""//我方把匹配上的字符替换成'*'返回
        public String content;
    }
}
